package com.iot.ammeter.service.impl.web.campus;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.iot.ammeter.constant.Constant;
import com.iot.ammeter.dto.web.campus.BuildingDTO;
import com.iot.ammeter.entity.web.campus.Building;
import com.iot.ammeter.entity.web.campus.Room;
import com.iot.ammeter.exception.BusinessExceptions;
import com.iot.ammeter.mapper.web.campus.BuildingMapper;
import com.iot.ammeter.mapper.web.campus.RoomMapper;
import com.iot.ammeter.query.web.campus.BuildingQuery;
import com.iot.ammeter.service.web.campus.BuildingService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iot.ammeter.utils.SnowFlakeIdWorker;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 楼栋 服务实现类
 * </p>
 *
 * @author basil
 * @since 2021-09-25
 */
@Service
public class BuildingServiceImpl extends ServiceImpl<BuildingMapper, Building> implements BuildingService {


    private final SnowFlakeIdWorker snowFlakeIdWorker;
    private final BuildingMapper buildingMapper;
    private final RoomMapper roomMapper;

    public BuildingServiceImpl(SnowFlakeIdWorker snowFlakeIdWorker, BuildingMapper buildingMapper, RoomMapper roomMapper) {
        this.snowFlakeIdWorker = snowFlakeIdWorker;
        this.buildingMapper = buildingMapper;
        this.roomMapper = roomMapper;
    }

    /**
     * 添加楼栋信息
     *
     * @param buildingDTO 楼栋信息
     * @return 添加成功或者添加失败
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String addBuilding(BuildingDTO buildingDTO) {
        /**
         * 实体校验
         */
        String campusId = buildingDTO.getCampusId().trim();
        String buildingName = buildingDTO.getBuildingName().trim();
        String remark = buildingDTO.getRemark().trim();
        if (StringUtils.isEmpty(campusId)) {
            throw new BusinessExceptions("校区id不能为空。");
        }
        if (StringUtils.isEmpty(buildingName)) {
            throw new BusinessExceptions("楼栋名称不能为空。");
        }
        /**
         * 检查对应校区下的楼栋是否已经存在
         */
        LambdaQueryWrapper<Building> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Building::getBuildingName, buildingName).eq(Building::getCampusId, campusId);
        if (buildingMapper.selectOne(queryWrapper) != null) {
            throw new BusinessExceptions("楼栋已存在。");
        }
        String buildingId = String.valueOf(snowFlakeIdWorker.nextId());
        /**
         * 补全数据
         */
        Building buildingToDb = new Building();
        buildingToDb.setBuildingId(buildingId);
        buildingToDb.setBuildingName(buildingName);
        buildingToDb.setIsDeleted(Constant.Building.NORMAL);
        buildingToDb.setCampusId(campusId);
        buildingToDb.setRemark(remark);
        buildingToDb.setCreateTime(LocalDateTime.now());
        buildingToDb.setUpdateTime(LocalDateTime.now());
        /**
         * 保存至数据库
         */
        int result = buildingMapper.insert(buildingToDb);
        return result > 0 ? "添加成功" : "添加失败";
    }

    /**
     * 编辑楼栋信息
     *
     * @param buildingId  楼栋id
     * @param buildingDTO 楼栋信息
     * @return ResponseResult
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String editBuilding(String buildingId, BuildingDTO buildingDTO) {
        /**
         * 实体校验
         */
        if (StringUtils.isEmpty(buildingId)) {
            throw new BusinessExceptions("楼栋id不能为空。");
        }
        String buildingName = buildingDTO.getBuildingName().trim();
        String campusId = buildingDTO.getCampusId().trim();
        if (StringUtils.isEmpty(buildingName)) {
            throw new BusinessExceptions("楼栋名称不能为空。");
        }
        if (StringUtils.isEmpty(campusId)) {
            throw new BusinessExceptions("校区id不能为空。");
        }
        /**
         * 对应楼栋是否存在
         */
        LambdaQueryWrapper<Building> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Building::getBuildingName, buildingName).eq(Building::getCampusId, campusId);
        if (buildingMapper.selectOne(queryWrapper) != null) {
            throw new BusinessExceptions("楼栋已存在。");
        }
        Building buildingFromDb = buildingMapper.selectById(buildingId);
        if (buildingFromDb == null) {
            throw new BusinessExceptions("楼栋信息不存在。");
        }
        /**
         * 更新
         */
        buildingFromDb.setBuildingName(buildingName);
        buildingFromDb.setCampusId(campusId);
        buildingFromDb.setRemark(buildingDTO.getRemark());
        buildingFromDb.setUpdateTime(LocalDateTime.now());
        int result = buildingMapper.updateById(buildingFromDb);
        return result > 0 ? "更新楼栋信息成功" : "更新楼栋信息失败";
    }

    /**
     * 获取楼栋信息列表
     *
     * @param page          请求页码
     * @param pageSize      每页数量
     * @param buildingQuery 楼栋查询条件
     * @return ResponseResult
     */
    @Override
    public IPage<BuildingDTO> getBuildingList(int page, int pageSize, BuildingQuery buildingQuery) {

        /**
         * 封装page对象
         */
        Page<BuildingDTO> pages = new Page<>(page, pageSize);
        IPage<BuildingDTO> listBuildings = buildingMapper.listBuildings(pages, buildingQuery);
        return listBuildings;
    }

    /**
     * 批量添加楼栋信息
     *
     * @param buildingDTO 楼栋信息
     * @return ResponseResult
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String batchAddBuilding(BuildingDTO buildingDTO) {
        /**
         * 数据校验
         */
        String campusId = buildingDTO.getCampusId().trim();
        String remark = buildingDTO.getRemark().trim();
        List<String> buildingNames = buildingDTO.getBuildingNames();
        if (StringUtils.isEmpty(campusId)) {
            throw new BusinessExceptions("校区id不能为空。");
        }
        if (buildingNames.isEmpty()) {
            throw new BusinessExceptions("楼栋名称不能为空。");
        }
        /**
         * 创建楼栋集合
         */
        List<Building> buildings = new ArrayList<>();
        Building buildingToDb = null;
        for (String buildingName : buildingNames) {
            buildingToDb = new Building();
            buildingToDb.setCampusId(campusId);
            buildingToDb.setRemark(remark);
            buildingToDb.setIsDeleted(Constant.Building.NORMAL);
            buildingToDb.setCreateTime(LocalDateTime.now());
            buildingToDb.setUpdateTime(LocalDateTime.now());
            buildingToDb.setBuildingId(String.valueOf(snowFlakeIdWorker.nextId()));
            buildingToDb.setBuildingName(buildingName);
            buildings.add(buildingToDb);
        }
        /**
         * 批量插入
         */
        Integer result = buildingMapper.insertBatchSomeColumn(buildings);
        return result > 0 ? "批量添加成功" : "批量添加失败";
    }

    /**
     * 删除楼栋（逻辑删除）
     *
     * @param buildingIds 楼栋id集合
     * @return 删除成功或者失败
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String batchDelBuilding(String[] buildingIds) {
        /**
         * 1.判断buildingIds是否为空
         * 2.判断楼栋下是否有房间信息，有则删除失败
         * 3.批量删除
         */
        if (buildingIds.length <= 0) {
            throw new BusinessExceptions("楼栋id不能为空。");
        }
        Integer count = roomMapper.selectCount(new LambdaQueryWrapper<Room>().in(Room::getBuildingId, Arrays.asList(buildingIds)));
        if (count > 0) {
            throw new BusinessExceptions("楼栋删除失败，该楼栋下含有房间信息。");
        }
        int result = buildingMapper.deleteBatchIds(Arrays.asList(buildingIds));
        return result > 0 ? "楼栋删除成功" : "楼栋删除失败";
    }

    /**
     * 导出楼栋列表
     *
     * @param buildingQuery 查询条件
     * @return 楼栋列表集合
     */
    @Override
    public List<BuildingDTO> exportBuildingList(BuildingQuery buildingQuery) {
        /**
         * 封装page对象
         */
        Page<BuildingDTO> pages = new Page<>();
        IPage<BuildingDTO> iPage = buildingMapper.listBuildings(pages, buildingQuery);
        return iPage.getRecords();
    }
}
